package com.easonji.core.shiro.factory;

import java.util.List;

import javax.annotation.Resource;

import com.easonji.admin.manager.UserManager;
import com.easonji.admin.mapper.UserAppMapper;
import com.easonji.admin.mapper.UserMapper;
import com.easonji.admin.model.User;
import com.easonji.admin.model.UserApp;
import com.easonji.core.shiro.ShiroUser;
import org.apache.shiro.authc.CredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.util.ByteSource;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.easonji.admin.manager.DeptManager;
import com.easonji.admin.manager.PermissionManager;
import com.easonji.common.constant.Consts;
import com.easonji.common.constant.enums.UserStatusEnum;
import com.easonji.common.util.SpringContextHolder;
import com.easonji.common.util.StringUtils;
import com.easonji.core.exception.BizException;

/**
 * @ClassName: ShiroFactroyImpl
 * @Description: 定义shirorealm所需数据的实现类
 * @Author: LiuJun
 * @date: 2018/07/10 14:00
 * @Version: 1.0
 * @Copyright: Copyright (c) 2018 - 2019
 */
@Service
@DependsOn("springContextHolder")
@Transactional(readOnly = true, rollbackFor = BizException.class)
public class ShiroFactroyImpl implements ShiroFactory {

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserManager userManager;

    @Resource
    private PermissionManager permissionManager;

    @Resource
    private DeptManager deptManager;

    @Resource
    private UserAppMapper userAppMapper;

    public static ShiroFactory me() {
        return SpringContextHolder.getBean(ShiroFactory.class);
    }

    @Override
    public User user(String account) {
        User param = new User();
        param.setAccount(account);
        User user = userMapper.selectOne(param);
        // 账号不存在
        if (StringUtils.isEmpty(user)) {
            throw new CredentialsException();
        }
        UserApp userAppParam = new UserApp();
        userAppParam.setUserId(user.getId());
        userAppParam.setAppId(Consts.DEFAULT_APP_ID);
        UserApp userApp = userAppMapper.selectOne(userAppParam);
        if (StringUtils.isEmpty(userApp)) {
            throw new CredentialsException();
        }
        // 账号被冻结
        if (StringUtils.notEquals(UserStatusEnum.OK.getCode(), user.getStatus())) {
            throw new LockedAccountException();
        }
        return user;
    }

    @Override
    public ShiroUser shiroUser(User user) {
        ShiroUser shiroUser = new ShiroUser();
        shiroUser.setUserId(user.getId());
        shiroUser.setAccount(user.getAccount());
        shiroUser.setDeptId(user.getDeptId());
        shiroUser.setPostId(user.getPost());
        shiroUser.setDeptName(deptManager.getDeptNameById(user.getDeptId()));
        shiroUser.setName(user.getName());
        shiroUser.setSex(user.getSex());
        shiroUser.setRoleIds(userManager.getRoleIdListByUserId(user.getId()));
        shiroUser.setRoleNames(userManager.getRoleNameListByUserId(user.getId()));
        return shiroUser;
    }

    @Override
    public List<String> findPermissionsByRoleIds(List<Integer> roleIds) {
        List<String> result = permissionManager.queryPermissionsByRoleIds(roleIds);
        return result;
    }

    @Override
    public SimpleAuthenticationInfo info(ShiroUser shiroUser, User user, String realmName) {
        String credentials = user.getPassword();
        // 密码加盐处理
        String source = user.getSalt();
        ByteSource credentialsSalt = new Md5Hash(source);
        return new SimpleAuthenticationInfo(shiroUser, credentials, credentialsSalt, realmName);
    }
}
